<template>
    <el-select
        v-model="selectValue"
        :loading="refreshLoading"
        filterable
        :popper-class="popperClass"
        remote
        remote-show-suffix
        :remote-method="remoteMethod"
        :placeholder="placeholder"
        clearable
        :multiple="multiple"
        @visible-change="visibleChange"
    >
        <template #loading>
            <div
                v-loading="refreshLoading"
                class="h-50"
                element-loading-background="rgba(255, 255, 255, 0.6)"
            ></div>
        </template>
        <template v-if="showHeader" #header>
            <slot name="header"></slot>
        </template>
        <el-option
            v-for="item in options"
            :key="item[value]"
            :label="item[label]"
            :value="item[value]"
        >
            <slot name="option" :option="item"></slot>
        </el-option>
        <!-- 添加空状态提示 -->
        <el-option
            v-if="!options.length && !refreshLoading"
            disabled
            label="无数据"
            value=""
            class="!cursor-initial text-center font-size-12 p-0 pt-10 pb-10 line-height-20"
        />
    </el-select>
</template>

<script setup>
import { ref, nextTick, useSlots } from "vue";
import { ElLoading } from "element-plus";

const slots = useSlots();
const showHeader = slots.hasOwnProperty("header");

// 选择器选中项的值
const selectValue = defineModel("selectValue", {
    require: true,
    type: [String, Number, Boolean, Object, Array],
});
// 选项列表
const options = defineModel("options", {
    require: true,
    type: Array,
});
// 数据回显时，会根据绑定的 select 的值依次查询选项详情，并增加到 options 中
// needFilterOptions 用于保存这些值，在查询分页接口时，会对接口返回值进行过滤
const needFilterOptions = defineModel("needFilterOptions", {
    type: Array,
});

const props = defineProps({
    // options value
    value: [String, Number, Boolean],
    // options label
    label: [String, Number],
    // 选择器自定义类名，用于获取dom监听滚动
    popperClass: {
        require: true,
        type: String,
    },
    placeholder: String,
    multiple: {
        type: Boolean,
        default: false,
    },
    // 接口请求函数，需要返回一个 promise
    apiFun: {
        require: true,
        type: Function,
    },
});

const currentPage = ref(1); // 当前页码
const totalNum = ref(0); // 总条数
const pageSize = ref(10); // 每页条数
const keyword = ref(null); // 远程搜索关键字
const refreshLoading = ref(false); // 当前是否在重新加载
const loading = ref(false); // 当前是否在加载
const isFinished = ref(false); // 数据是否完成

// 远程搜索接口
const getData = async () => {
    if (loading.value) return;

    let loadingInstance;

    if (!refreshLoading.value) {
        loadingInstance = ElLoading.service({
            target: `.${props.popperClass} .el-scrollbar`,
            background: "rgba(255, 255, 255, 0.6)",
        });
    }

    loading.value = true;

    const res = await props.apiFun({
        current: currentPage.value,
        size: pageSize.value,
        status: 0,
        keyword: keyword.value,
    });

    const { current, records, size, total } = res.data.data;

    // 对搜索结果进行过滤
    if (records.length && Array.isArray(needFilterOptions.value)) {
        // 需要过滤的选项 value 数组
        needFilterOptions.value.forEach((filterOption) => {
            // 接口返回数据是否有重复项
            const option = records.find(
                (item) => item[props.value] === filterOption[props.value]
            );
            // 删除 options 中的重复项
            if (option) {
                const optionsIndex = options.value.findIndex(
                    (item) => item[props.value] === option[props.value]
                );
                if (optionsIndex > -1) {
                    options.value.splice(optionsIndex, 1);
                }
            }
        });
    }

    options.value.push(...records);
    currentPage.value = Number(current);
    pageSize.value = Number(size);
    totalNum.value = Number(total);

    if (totalNum.value <= pageSize.value * currentPage.value) {
        isFinished.value = true;
    } else {
        isFinished.value = false;
        currentPage.value++;
    }

    nextTick(() => {
        loadingInstance && loadingInstance.close();
        loading.value = false;

        // 当修改每页条数时，解决 options 未撑满容器没有出现滚动条无法加载更多的问题
        if (!isFinished.value && options.value.length < 10) {
            getData();
        }
    });
};

// 下拉加载更多
const selectLoadMore = () => {
    if (isFinished.value) return;
    getData();
};

// 远程搜索
const remoteMethod = (query) => {
    // 重置搜索条件并清空选项列表
    currentPage.value = 1;
    refreshLoading.value = true;
    options.value = [];
    nextTick(() => {
        if (query) {
            keyword.value = query;
            // 如果需要过滤的选项中包含当前搜索关键字，则将选项添加到选项列表中
            const option = needFilterOptions.value?.find(
                (item) => item[props.label] === keyword.value
            );
            if (option) options.value.push(option);
        } else {
            // 无搜索关键字则将需要过滤的选项添加进选项中
            if (needFilterOptions.value) {
                options.value.push(...needFilterOptions.value);
            }
            keyword.value = null;
        }
        getData().then(() => {
            refreshLoading.value = false;
        });
    });
};

// 滚动到底部加载更多
function scrollEvent() {
    if (this.scrollHeight - this.scrollTop - 1 <= this.clientHeight) {
        selectLoadMore();
    }
}

const visibleChange = (e) => {
    const selectWrapDom = document.querySelector(
        `.${props.popperClass} .el-scrollbar .el-select-dropdown__wrap`
    );
    if (e) {
        selectWrapDom.addEventListener("scroll", scrollEvent);
    } else {
        selectWrapDom.removeEventListener("scroll", scrollEvent);
    }
};
</script>
